/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "数据缓存.h"
#include "节点/插座/通用插座.h"
#include "节点/插座/list/list数值插座.h"
#include "节点/插座/list/list物体插座.h"
#include "节点/插座/list/list物理物体插座.h"
#include "Context/数据创建销毁.h"





C_数据缓存写入节点::C_数据缓存写入节点(S_设备环境& ctx) : C_节点基类("数据缓存写入节点") {
	m_Name = L"数据缓存写入";

	C_插座基类* socket;
	DEF_创建引用插座_I(L"源");
	DEF_创建UI32插座_I(L"帧");
	//DEF_通用数据插座创建_O(L"合并数据");


	m_Path = f_alloc_PathProp(nullptr, L"保存路径");
	m_Path.m_私有 = true;

	//m_方式 = f_alloc_EnumProp({ {L"打开", ""}, {L"保存", ""} }, L"方式");
	//m_方式.m_私有 = true;

	m_格式 = f_alloc_EnumProp(nullptr, { 
		{L"geom", ""},
		{L"vdb", ""}, 
		{L"PBF", ""} 
	}, L"格式");
	m_格式.m_私有 = true;

	m_文件名 = f_alloc_StrProp(nullptr, L"文件名");
	m_文件名.m_私有 = true;

}

C_数据缓存写入节点::~C_数据缓存写入节点() {
	f_prop_Release(m_Path);
	f_prop_Release(m_文件名);
	f_release_EnumProp(m_格式);
}

bool C_数据缓存写入节点::f_update() {
	auto& inData = *DEF_引用插座数据(f_get输入插座(1), 0);


	FILE* f;
	std::string path = f_prop_Path(m_Path).string();
	f = fopen(path.c_str(), "wb");
	if (f) {
		uint32 type = inData.m_Type;
		fwrite(&type, sizeof(uint32), 1, f);

		switch (inData.m_Type)
		{
		case E_值类型::e_Type_Vec3_Array1D:
			file_写入序列到文件(f, *DEF_引用转Vec3_1D(inData));
			break;
		case E_值类型::e_Type_Vec4_Array1D:
			file_写入序列到文件(f, *DEF_引用转Vec4_1D(inData));
			break;
		case E_值类型::e_Type_VecSphere_1D:
			file_写入序列到文件(f, *DEF_引用转VecSphere_1D(inData));
			break;

		case E_值类型::e_插座Type_物理解算器:
			break;
		default:
			break;
		}

		fclose(f);
	}

	return false;
}

void C_数据缓存写入节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	f_prop_Load(m_Path, f);
	f_prop_Load(m_格式, f);
	f_prop_Load(m_文件名, f);
}

void C_数据缓存写入节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	f_prop_Save(m_Path, f);
	f_prop_Save(m_格式, f);
	f_prop_Save(m_文件名, f);
}

C_节点基类* f_node_加载写入数据缓存节点(S_设备环境& ctx, FILE* f) {
	C_数据缓存写入节点* node = new C_数据缓存写入节点(ctx);
	return node;
}

void f_node_保存写入数据缓存节点(C_节点基类* n, FILE* f) {
	C_数据缓存写入节点* node = dynamic_cast<C_数据缓存写入节点*>(n);
}












C_数据缓存读取节点::C_数据缓存读取节点(S_设备环境& ctx) : C_节点基类("数据缓存读取节点") {
	m_Name = L"数据缓存读取";

	C_插座基类* socket;
	DEF_创建UI32插座_I(L"帧");
	DEF_通用数据插座创建_O(L"数据");


	m_Path = f_alloc_PathProp(nullptr, L"保存路径");
	m_Path.m_私有 = true;

	//m_方式 = f_alloc_EnumProp({ {L"打开", ""}, {L"保存", ""} }, L"方式");
	//m_方式.m_私有 = true;

	m_格式 = f_alloc_EnumProp(nullptr, { {L"geom", ""}, {L"vdb", ""}, {L"PBF", ""} }, L"格式");
	m_格式.m_私有 = true;

	m_文件名 = f_alloc_StrProp(nullptr, L"文件名");
	m_文件名.m_私有 = true;
}

C_数据缓存读取节点::~C_数据缓存读取节点() {
}

bool C_数据缓存读取节点::f_update() {
	FILE* f;
	std::string path = f_prop_Path(m_Path).string();
	f = fopen(path.c_str(), "rb");
	if (f) {
		uint32 type = 0;
		fread(&type, sizeof(uint32), 1, f);

		E_值类型 outType = E_值类型(type);

		switch (outType)
		{
		case E_值类型::e_Type_Vec3_Array1D: {
			std::vector<vec3> outData;
			f_读取文件(f, &outData);
			break;
		}
		case E_值类型::e_Type_Vec4_Array1D: {
			std::vector<vec4> outData;
			f_读取文件(f, &outData);
			break;
		}
		case E_值类型::e_Type_VecSphere_1D: {
			std::vector<S_VecSphere> outData;
			f_读取文件(f, &outData);
			break;
		}
		default:
			break;
		}


		fclose(f);
	}

	return false;
}

void C_数据缓存读取节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	f_prop_Load(m_Path, f);
	f_prop_Load(m_格式, f);
	f_prop_Load(m_文件名, f);
}

void C_数据缓存读取节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	f_prop_Save(m_Path, f);
	f_prop_Save(m_格式, f);
	f_prop_Save(m_文件名, f);
}

C_节点基类* f_node_加载数据缓存读取节点(S_设备环境& ctx, FILE* f) {
	C_数据缓存读取节点* node = new C_数据缓存读取节点(ctx);
	return node;
}

void f_node_保存数据缓存读取节点(C_节点基类* n, FILE* f) {
	C_数据缓存读取节点* node = dynamic_cast<C_数据缓存读取节点*>(n);
}






C_物体缓存节点::C_物体缓存节点(S_设备环境& ctx) : C_节点基类(DEF_物体缓存节点) {
	m_Name = L"物体缓存";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物体_1D插座_I(L"物体");
	DEF_创建物体_1D插座_O(L"物体");

	m_Path = f_alloc_PathProp(nullptr, L"文件路径");
	m_Path.m_私有 = true;

	m_类型 = f_alloc_EnumProp(nullptr, {
	    {L"物体",""},
		{L"网格",""},
		{L"多边形",""},
		{L"顶点",""},
	}, L"缓存类型");
	m_类型.m_私有 = true;

	m_应用变换 = f_alloc_BoolProp(nullptr, L"应用变换");
	m_应用变换.m_私有 = true;
	f_prop_Bool(m_应用变换) = false;

	m_中心变换方式 = f_alloc_EnumProp(nullptr, {
		{L"保存偏移",""},
		{L"世界原点",""},
		{L"原物体",""},
		}, L"中心变换");
	m_中心变换方式.m_私有 = true;
	f_prop_enum(m_中心变换方式) = 0;


	m_实时写入 = f_alloc_BoolProp(nullptr, L"实时写入");
	m_实时写入.m_私有 = true;
	f_prop_Bool(m_实时写入) = false;


	m_上一次加载路径 = std::filesystem::temp_directory_path().string();
}

C_物体缓存节点::~C_物体缓存节点() {
	f_prop_Release(m_Path);
	f_prop_Release(m_类型);
	f_prop_Release(m_应用变换);
	f_prop_Release(m_中心变换方式);
	f_prop_Release(m_实时写入);
}

bool C_物体缓存节点::f_update() {
	auto& OutObjs = *DEF_物体插座_1D数据(f_get输出插座(1), 0);

	auto socket1 = f_get输入插座(1);

	auto 路径 = f_prop_Path(m_Path).string();
	std::string 拼接路径 = f_nodeCtx_相对路径补全(路径);


	if (m_冻结数据 || socket1->f_isLink() == false) {
		if(m_上一次加载路径 == 拼接路径) return false;
		if (m_上一次加载路径 != 拼接路径) {
			m_上一次加载路径 = 拼接路径;

			for (uint32 i = 0; i < OutObjs.count; ++i) {
				//f_node_销毁模型网格(OutObjs->ptr_userData[i]);
				f_node_从主场景移除物体(OutObjs.ptr_userData[i]);
				f_node_物体从全局容器移除(OutObjs.ptr_userData[i]);
			}
			f_node_删除物体(&OutObjs);

			if(f_file_文件是否存在(m_上一次加载路径) == false) return false;

			FILE* f = fopen(拼接路径.c_str(), "rb");
			if (f) {
				//auto* OutObjs = DEF_物体插座_1D数据(f_get输出插座(1), 0);
				f_ob_Load多物体(&OutObjs, f, m_Ctx, true);

				fclose(f);
			}


			for (uint32 i=0; i<OutObjs.count; ++i) {
				
				switch (OutObjs.ptr_userData[i]->m_Type) {
				case E_物体类型::t_多边形: {
					f_node_构建多边形网格对象(m_Ctx, OutObjs.ptr_userData[i]);

					S_Mesh* 轮廓 = f_ob_fromMesh(OutObjs.ptr_userData[i], 0);
					S_Mesh* 面网格 = f_ob_fromMesh(OutObjs.ptr_userData[i], 1);
					S_Mesh* 点网格 = f_ob_fromMesh(OutObjs.ptr_userData[i], 2);
					S_Mesh* 边网格 = f_ob_fromMesh(OutObjs.ptr_userData[i], 3);
					f_surface_多边形转网格((S_多边形*)OutObjs.ptr_userData[i]->m_UserData, 面网格, 点网格, 边网格, true);

					f_surface_计算包围盒(轮廓);
					break;
				}
				}
			}

			uint32 num = DEF_Min(m_变换组.size(), OutObjs.count);
			f_get输出插座(1)->m_有新数据 = true;
			for (uint32 i = 0; i < num; ++i) {
				OutObjs.ptr_userData[i]->m_变换 = m_变换组[i];
			}
			m_变换组.clear();

			f_node_物体添加到主场景(&OutObjs);
		}
	}
	else {
		auto* InObjs = DEF_物体插座_1D数据(socket1, 0);

		f_node_删除物体(&OutObjs);
		
		//if (socket1->m_有新数据 == false) return false;
		if (InObjs->count) {
			auto 路径 = 拼接路径;
			//if(路径 == m_上一次加载路径) return false;

			FILE* f = fopen(路径.c_str(), "wb");
			if (f) {
				f_core_array_resize((S_Array*)&OutObjs, InObjs->count);

				m_上一次加载路径 = 路径;

				for (uint32 i=0; i<InObjs->count; ++i) {
					OutObjs.ptr_userData[i] = f_ob_copy(m_Ctx, InObjs->ptr_userData[i], false);
					f_TranformInit(OutObjs.ptr_userData[i]->m_变换);
					f_ob_set矩阵(OutObjs.ptr_userData[i], f_mat44_identity());
				}

				f_ob_Save多物体(&OutObjs, f, true);

				fclose(f);


				for (uint32 i=0; i<OutObjs.count; ++i) {
					auto mat = f_mat44_构建XYZ变换矩阵(InObjs->ptr_userData[i]->m_变换);
					//auto mat = f_ob_get变换矩阵(OutObjs->ptr_userData[i]);

					switch (OutObjs.ptr_userData[i]->m_Type) {
					case E_物体类型::t_多边形: {
						f_node_构建多边形网格对象(m_Ctx, OutObjs.ptr_userData[i]);
						
						S_Mesh* 轮廓 = f_ob_fromMesh(OutObjs.ptr_userData[i], 0);
						S_Mesh* 面网格 = f_ob_fromMesh(OutObjs.ptr_userData[i], 1);
						S_Mesh* 点网格 = f_ob_fromMesh(OutObjs.ptr_userData[i], 2);
						S_Mesh* 边网格 = f_ob_fromMesh(OutObjs.ptr_userData[i], 3);
						f_surface_多边形转网格((S_多边形*)OutObjs.ptr_userData[i]->m_UserData, 面网格, 点网格, 边网格, true);

						if (f_prop_Bool(m_应用变换)) {
							f_surface_应用变换(面网格, mat);
							f_surface_应用变换(点网格, mat);
							f_surface_应用变换(边网格, mat);
						}

						f_surface_计算包围盒(轮廓);
						break;
					}
					case E_物体类型::t_网格: {
						break;
					}
					}
				}
				f_node_物体添加到主场景(&OutObjs);
			}
		}
	}

	return false;
}

void C_物体缓存节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	//if (S_引擎::读取加载文件版本号 == 0) {
	//	f_prop_Load(m_Path, f);
	//	f_prop_Load(m_类型, f);
	//	f_prop_Load(m_应用变换, f);
	//	f_prop_Load(m_中心变换方式, f);
	//}
	//else {
	//	
	//}
	
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
	
		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_Path, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_类型, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_应用变换, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_中心变换方式, 下一次读取数据指针);

			m_变换组.clear();
			下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, m_变换组, false);
		}
	}
	free(文件块.m_data);
}

void C_物体缓存节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_Path, 块);
	f_prop_Save(m_类型, 块);
	f_prop_Save(m_应用变换, 块);
	f_prop_Save(m_中心变换方式, 块);


	auto* OutObjs = DEF_物体插座_1D数据(f_get输出插座(1), 0);
	m_变换组.clear();
	for (uint32 i = 0; i < OutObjs->count; ++i) {
		m_变换组.push_back(OutObjs->ptr_userData[i]->m_变换);
	}
	f_文件块_写序列数据块(块, m_变换组, false);


	f_file_保存文件块(f, 文件块, 块);
}

S_物体* C_物体缓存节点::f_get虚拟体() {
	auto* objs = DEF_物体插座_1D数据(f_get输出插座(1), 0);
	for (uint32 i = 0; i < objs->count; ++i) {
		if(!objs->ptr_userData[i]) continue;

		switch (objs->ptr_userData[i]->m_Type) {
		case E_物体类型::t_多边形:
		case E_物体类型::t_网格: {
			return objs->ptr_userData[i];
		}
		}
	}
	return nullptr;
}

void C_物体缓存节点::f_入回收() {
	auto* objs = DEF_物体插座_1D数据(f_get输出插座(1), 0);
	f_node_物体添加到主场景(objs);
}

void C_物体缓存节点::f_回收() {
	auto* objs = DEF_物体插座_1D数据(f_get输出插座(1), 0);
	f_node_从主场景移除物体(objs);
}

void C_物体缓存节点::f_Show(bool open) {
	auto* objs = DEF_物体插座_1D数据(f_get输出插座(1), 0);
	for (uint32 i = 0; i < objs->count; ++i) {
		objs->ptr_userData[i]->m_渲染 = open;
	}
}

C_节点基类* f_node_创建物体缓存节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_物体缓存节点(ctx);
}

C_节点基类* f_node_加载物体缓存节点(S_设备环境& ctx, FILE* f) {
	C_物体缓存节点* node = new C_物体缓存节点(ctx);
	return node;
}

void f_node_保存物体缓存节点(C_节点基类* n, FILE* f) {
	C_物体缓存节点* node = dynamic_cast<C_物体缓存节点*>(n);
}





C_网格缓存写入节点::C_网格缓存写入节点(S_设备环境& ctx) : C_节点基类(DEF_网格缓存写入节点) {
	m_Name = L"网格缓存写入";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物体_1D插座_I(L"物体");
	DEF_创建I32插座_I(L"帧");
	//DEF_创建物体_1D插座_O(L"物体");

	m_Path = f_alloc_PathProp(nullptr, L"文件路径");
	m_Path.m_私有 = true;

	m_文件名称 = f_alloc_LineStrProp(nullptr, L"文件名称");
	m_文件名称.m_私有 = true;

	m_覆盖文件 = f_alloc_BoolProp(nullptr, L"覆盖文件");
	m_覆盖文件.m_私有 = true;
	f_prop_Bool(m_覆盖文件) = true;

	m_序列文件 = f_alloc_BoolProp(nullptr, L"序列文件");
	m_序列文件.m_私有 = true;
	f_prop_Bool(m_序列文件) = false;

	m_元素 = f_alloc_bool_1DProp(4, L"缓存类型");
	m_元素.m_私有 = true;
	S_PropVecBool* 元素开关 = f_prop_Bool_1D(m_元素);
	元素开关[0].m_Names = L"顶点"; 元素开关[0].m_ICO = "三角顶点"; 元素开关[0].m_Value = true;
	元素开关[1].m_Names = L"法线"; 元素开关[1].m_ICO = "平面法线"; 元素开关[1].m_Value = true;
	元素开关[2].m_Names = L"UV"; 元素开关[2].m_ICO = "材质"; 元素开关[2].m_Value = false;
	元素开关[3].m_Names = L"索引"; 元素开关[3].m_ICO = "指示ID"; 元素开关[3].m_Value = false;
	
	m_应用变换 = f_alloc_BoolProp(nullptr, L"应用变换");
	m_应用变换.m_私有 = true;
	f_prop_Bool(m_应用变换) = false;

	m_中心变换方式 = f_alloc_EnumProp(nullptr, {
		{L"保存偏移",""},
		{L"世界原点",""},
		{L"原物体",""},
		}, L"中心变换");
	m_中心变换方式.m_私有 = true;
	f_prop_enum(m_中心变换方式) = 0;


	m_压缩 = f_alloc_BoolProp(nullptr, L"压缩");
	m_压缩.m_私有 = true;
	f_prop_Bool(m_压缩) = false;


	m_压缩等级 = f_alloc_I32Prop(nullptr, L"压缩等级");
	m_压缩等级.m_私有 = true;
	f_prop_I32(m_压缩等级) = 1;


	m_实时写入 = f_alloc_BoolProp(nullptr, L"实时写入");
	m_实时写入.m_私有 = true;
	f_prop_Bool(m_实时写入) = false;


	m_上一次加载路径 = std::filesystem::temp_directory_path().string();

	f_prop_LineStr(m_文件名称) = m_Name;
}

C_网格缓存写入节点::~C_网格缓存写入节点() {
	f_prop_Release(m_Path);
	f_prop_Release(m_文件名称);
	f_prop_Release(m_覆盖文件);
	f_prop_Release(m_序列文件);
	f_prop_Release(m_元素);
	f_prop_Release(m_应用变换);
	f_prop_Release(m_中心变换方式);
	f_prop_Release(m_压缩);
	f_prop_Release(m_压缩等级);
	f_prop_Release(m_实时写入);
}

bool C_网格缓存写入节点::f_update() {
	//auto* OutObjs = DEF_物体插座_1D数据(f_get输出插座(1), 0);
	auto path = f_prop_Path(m_Path).string();
	std::string 拼接路径 = f_nodeCtx_相对路径补全(path);

	


	auto socket1 = f_get输入插座(1);
	auto socket2 = f_get输入插座(2);
	auto* InObjs = DEF_物体插座_1D数据(socket1, 0);
	
	bool 序列 = f_prop_Bool(m_序列文件);
	std::string 帧;
	if (序列) {
		if (socket2->f_isLink()) {
			帧 = f_整数值转字符串(DEF_I32插座数据(socket2));
		}
		else {
			帧 = f_整数值转字符串(f_prop_I32(f_NodeCtx_get帧().当前帧));
		}
		m_更新方式 = E_节点更新方式::e_节点更新_逐帧;
	}
	else {
		m_更新方式 = E_节点更新方式::e_节点更新_被动;
	}
	
	
	auto name = f_WStringToString(f_prop_LineStr(m_文件名称));
	拼接路径 += "/" + name + "/";


	if (f_file_文件是否存在(拼接路径) == false) {
		f_file_创建目录(拼接路径);
	}

	for (uint32 i = 0; i < InObjs->count; ++i) {
		auto 路径 = 拼接路径;
		if (序列) {
			路径 = 路径 + name + f_整数值转字符串(i) + "_" + 帧 + ".mesh_cache";
		}
		else {
			路径 = 路径 + name + f_整数值转字符串(i) + ".mesh_cache";
		}


		FILE* F = fopen(路径.c_str(), "wb");
		if (F) {
			auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_网格缓存, S_节点数据::g_文件版本号);
			S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));


			std::string 文件头 = "mesh_cache";
			f_包字符串(块, 文件头);

			S_PropVecBool* 元素开关 = f_prop_Bool_1D(m_元素);
			uint8 mask = 0;
			for(int32 i=0; i<4; ++i) if(元素开关[i].m_Value) mask |= 1<<i;
			//fwrite(&mask, sizeof(uint8), 1, F);
			f_文件块_写数据块(块, &mask, sizeof(uint8));
			f_文件块_写数据块(块, (uint8*)&f_prop_Bool(m_压缩), sizeof(bool));
			

			if (元素开关[0].m_Value) {
				std::vector<vec3> 坐标;
				f_surface_get顶点坐标(f_ob_fromMesh(InObjs->ptr_userData[i], 1), 坐标);

				f_文件块_写序列数据块(块, 坐标, f_prop_Bool(m_压缩));
			}
			if (元素开关[1].m_Value) {
				std::vector<vec3> 法线;
				f_surface_get顶点法线(f_ob_fromMesh(InObjs->ptr_userData[i], 1), 法线);

				f_文件块_写序列数据块(块, 法线, f_prop_Bool(m_压缩));
			}
			if (元素开关[2].m_Value) {
				//std::vector<vec3> 法线;
				//f_surface_get顶点法线(f_ob_fromMesh(InObjs->ptr_userData[i], 1), 法线);
				//
				//f_文件块_写序列数据块(块, 法线, f_prop_Bool(m_压缩));
			}
			if (元素开关[3].m_Value) {
				std::vector<uint32> 索引;
				f_surface_get顶点索引(f_ob_fromMesh(InObjs->ptr_userData[i], 1), 索引);

				f_文件块_写序列数据块(块, 索引, f_prop_Bool(m_压缩));
			}
			
			f_file_保存文件块(F, 文件块, 块);
			fclose(F);
		}
	}
	return false;
}

void C_网格缓存写入节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_Path, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_文件名称, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_覆盖文件, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_序列文件, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_元素, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_应用变换, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_中心变换方式, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_压缩, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_压缩等级, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_网格缓存写入节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_Path, 块);
	f_prop_Save(m_文件名称, 块);
	f_prop_Save(m_覆盖文件, 块);
	f_prop_Save(m_序列文件, 块);
	f_prop_Save(m_元素, 块);
	f_prop_Save(m_应用变换, 块);
	f_prop_Save(m_中心变换方式, 块);
	f_prop_Save(m_压缩, 块);
	f_prop_Save(m_压缩等级, 块);

	f_file_保存文件块(f, 文件块, 块);
}

S_物体* C_网格缓存写入节点::f_get虚拟体() {
	return nullptr;
}

void C_网格缓存写入节点::f_入回收()
{
}

void C_网格缓存写入节点::f_回收()
{
}

void C_网格缓存写入节点::f_Show(bool open)
{
}

C_节点基类* f_node_创建网格缓存写入节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_网格缓存写入节点(ctx);
}

C_节点基类* f_node_加载网格缓存写入节点(S_设备环境& ctx, FILE* f) {
	C_网格缓存写入节点* node = new C_网格缓存写入节点(ctx);
	return node;
}

void f_node_保存网格缓存写入节点(C_节点基类* n, FILE* f) {
	C_网格缓存写入节点* node = dynamic_cast<C_网格缓存写入节点*>(n);
}





C_读取网格缓存节点::C_读取网格缓存节点(S_设备环境& ctx) : C_节点基类(DEF_读取网格缓存节点) {
	m_Name = L"读取网格缓存";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建物体_1D插座_I(L"物体");
	DEF_创建I32插座_I(L"帧");
	DEF_创建物体_1D插座_O(L"物体");

	m_Path = f_alloc_PathProp(nullptr, L"文件路径");
	m_Path.m_私有 = true;

	m_文件名称 = f_alloc_LineStrProp(nullptr, L"文件名称");
	m_文件名称.m_私有 = true;

	m_序列文件 = f_alloc_BoolProp(nullptr, L"序列文件");
	m_序列文件.m_私有 = true;
	f_prop_Bool(m_序列文件) = false;

	m_循环区间 = f_alloc_UI32Prop(nullptr, L"序列文件");
	m_循环区间.m_私有 = true;
	f_prop_UI32(m_循环区间) = 0;

	m_元素 = f_alloc_bool_1DProp(4, L"缓存类型");
	m_元素.m_私有 = true;
	S_PropVecBool* 元素开关 = f_prop_Bool_1D(m_元素);
	元素开关[0].m_Names = L"顶点"; 元素开关[0].m_ICO = "三角顶点"; 元素开关[0].m_Value = true;
	元素开关[1].m_Names = L"法线"; 元素开关[1].m_ICO = "平面法线"; 元素开关[1].m_Value = true;
	元素开关[2].m_Names = L"UV"; 元素开关[2].m_ICO = "材质"; 元素开关[2].m_Value = false;
	元素开关[3].m_Names = L"索引"; 元素开关[3].m_ICO = "指示ID"; 元素开关[3].m_Value = false;


	m_应用变换 = f_alloc_BoolProp(nullptr, L"应用变换");
	m_应用变换.m_私有 = true;
	f_prop_Bool(m_应用变换) = true;

	m_中心变换方式 = f_alloc_EnumProp(nullptr, {
		{L"保存偏移",""},
		{L"世界原点",""},
		{L"原物体",""},
		}, L"中心变换");
	m_中心变换方式.m_私有 = true;
	f_prop_enum(m_中心变换方式) = 0;

	m_上一次加载路径 = std::filesystem::temp_directory_path().string();
}

C_读取网格缓存节点::~C_读取网格缓存节点() {
	f_prop_Release(m_Path);
	f_prop_Release(m_文件名称);
	f_prop_Release(m_序列文件);
	f_prop_Release(m_应用变换);
	f_prop_Release(m_中心变换方式);
}

bool C_读取网格缓存节点::f_update() {
	auto path = f_prop_Path(m_Path).string();
	std::string 拼接路径 = f_nodeCtx_相对路径补全(path);

	if (f_file_文件是否存在(拼接路径) == false) return false;

	

	auto socket1 = f_get输入插座(1);
	auto socket2 = f_get输入插座(2);
	auto* InObjs = DEF_物体插座_1D数据(socket1, 0);
	std::string 帧;

	bool 序列 = f_prop_Bool(m_序列文件);
	if (序列) {
		if (socket2->f_isLink()) {
			帧 = f_整数值转字符串(DEF_I32插座数据(socket2));
		}
		else {
			帧 = f_整数值转字符串(f_prop_I32(f_NodeCtx_get帧().当前帧));
		}
		m_更新方式 = E_节点更新方式::e_节点更新_逐帧;
	}
	else {
		m_更新方式 = E_节点更新方式::e_节点更新_被动;
	}


	auto name = f_WStringToString(f_prop_LineStr(m_文件名称));
	if (name.empty()) {
		name = f_prop_Path(m_Path).filename().string();
	}
	else {
		拼接路径 += "/" + name;
	}
	拼接路径 += "/";
	

	

	auto* OutObjs = DEF_物体插座_1D数据(f_get输出插座(1), 0);
	f_node_创建模型物体组(OutObjs, InObjs->count, E_物体类型::t_网格, m_Ctx);


	for (uint32 i = 0; i < InObjs->count; ++i) {
		auto 路径 = 拼接路径;


		uint32 循环区间 = f_prop_UI32(m_循环区间);
		if (循环区间) {
			循环区间 = i - ((i / 循环区间) * 循环区间);
		}
		else {
			循环区间 = i;
		}

		if (序列) {
			路径 = 路径 + name + f_整数值转字符串(循环区间) + "_" + 帧 + ".mesh_cache";
		}
		else {
			路径 = 路径 + name + f_整数值转字符串(循环区间) + ".mesh_cache";
		}



		FILE* F = fopen(路径.c_str(), "rb");
		if (F) {
			S_文件块 文件块 = f_file_读取文件块(F);
			if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_网格缓存) {
				const uint8* 下一次读取数据指针 = 文件块.m_data;

				if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
					std::string 文件头;
					下一次读取数据指针 = f_解字符串(文件头, 下一次读取数据指针);
					

					if (文件头 == "mesh_cache") {
						S_PropVecBool* 元素开关 = f_prop_Bool_1D(m_元素);
						uint8 mask = 0;
						下一次读取数据指针 = f_文件块_取数据块(mask, 下一次读取数据指针);
						bool 是否压缩 = false;
						下一次读取数据指针 = f_文件块_取数据块(是否压缩, 下一次读取数据指针);


						if (mask & 1 << 3) {
							if (mask & 1 << 0) {
								std::vector<vec3> 坐标;
								下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, 坐标, 是否压缩);

								if (元素开关[0].m_Value) {
									f_surface_fill顶点数据(f_ob_fromMesh(InObjs->ptr_userData[i], 1), 坐标);
								}
								if (InObjs->ptr_userData[i]->m_Type == E_物体类型::t_多边形) {
									f_surface_fill顶点数据(f_ob_fromMesh(InObjs->ptr_userData[i], 2), 坐标);
								}
							}

							if (mask & 1 << 1) {
								std::vector<vec3> 法线;
								下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, 法线, 是否压缩);

								if (元素开关[1].m_Value) {
									f_surface_fill法线数据(f_ob_fromMesh(InObjs->ptr_userData[i], 1), 法线);
								}
							}

							if (mask & 1 << 2) {
								
							}


							std::vector<uint32> 索引;
							下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, 索引, 是否压缩);
							f_surface_fill索引数据(f_ob_fromMesh(InObjs->ptr_userData[i], 1), 索引);
						}
						else {
							if (mask & 1 << 0) {
								std::vector<vec3> 坐标;
								下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, 坐标, 是否压缩);

								if (元素开关[0].m_Value) {
									f_surface_set顶点数据(f_ob_fromMesh(InObjs->ptr_userData[i], 1), 坐标);
								}
								if (InObjs->ptr_userData[i]->m_Type == E_物体类型::t_多边形) {
									f_surface_set顶点数据(f_ob_fromMesh(InObjs->ptr_userData[i], 2), 坐标);
								}
							}

							if (mask & 1 << 1) {
								std::vector<vec3> 法线;
								下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, 法线, 是否压缩);

								if (元素开关[1].m_Value) {
									f_surface_set法线数据(f_ob_fromMesh(InObjs->ptr_userData[i], 1), 法线);
								}
							}
						}
						
						f_NodeCtx_get默认场景()->f_更新渲染物体();
					}
				}
			}

			free(文件块.m_data);
			fclose(F);
		}

		if (i < m_变换组.size()) {
			//InObjs->ptr_userData[i]->m_变换 = m_变换组[i];
		}
	}



	return false;
}

void C_读取网格缓存节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_1, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_Path, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_文件名称, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_序列文件, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_循环区间, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_元素, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_应用变换, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_中心变换方式, 下一次读取数据指针);


			m_变换组.clear();
			下一次读取数据指针 = f_文件块_读序列数据块(下一次读取数据指针, m_变换组, false);
		}
		else if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_Path, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_文件名称, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_序列文件, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_循环区间, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_元素, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_应用变换, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_中心变换方式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_读取网格缓存节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_Path, 块);
	f_prop_Save(m_文件名称, 块);
	f_prop_Save(m_序列文件, 块);
	f_prop_Save(m_循环区间, 块);
	f_prop_Save(m_元素, 块);
	f_prop_Save(m_应用变换, 块);
	f_prop_Save(m_中心变换方式, 块);


	auto* OutObjs = DEF_物体插座_1D数据(f_get输出插座(1), 0);
	m_变换组.clear();
	for (uint32 i = 0; i < OutObjs->count; ++i) {
		m_变换组.push_back(OutObjs->ptr_userData[i]->m_变换);
	}
	f_文件块_写序列数据块(块, m_变换组, false);


	f_file_保存文件块(f, 文件块, 块);
}

S_物体* C_读取网格缓存节点::f_get虚拟体() {
	return nullptr;
}

void C_读取网格缓存节点::f_入回收()
{
}

void C_读取网格缓存节点::f_回收()
{
}

void C_读取网格缓存节点::f_Show(bool open)
{
}

C_节点基类* f_node_创建读取网格缓存节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_读取网格缓存节点(ctx);
}

C_节点基类* f_node_加载读取网格缓存节点(S_设备环境& ctx, FILE* f) {
	C_读取网格缓存节点* node = new C_读取网格缓存节点(ctx);
	return node;
}

void f_node_保存读取网格缓存节点(C_节点基类* n, FILE* f) {
	C_读取网格缓存节点* node = dynamic_cast<C_读取网格缓存节点*>(n);
}











